<!--
 * SelectTable 下拉表格组件
 * @author: Goal
 * @since: 2023-11-13
 * SelectTable.vue
 *
 * 属性(带有[Required]为必填属性)
 * data[Required]: 双向绑定数据
 * fields[Required]: 表格列对象
 * tableData[Required]: 表格数据对象
 * value: 双向绑定数据的值(为空时data属性为表格当前行数据对象)
 * label: 选择框显示的文本内容(为空时分别查看value和objKey是否为空,若value和objKey都有值,则value优先级大于objKey)
 * objKey: 对象key(绑定值的唯一标识，绑定值为对象时必填)
 * placeholder: 选择框占位文本
 * size: 组件大小
 * border: 表格是否带有边框
 * clearable: 下拉框是否可清空
 * curPage: 表格分页当前页
 * pageSize: 表格分页每页总数
 * total: 表格总行数
 * pageLayout: 分页按钮布局(参考elementplus)
 * hideOnSinglePage: 在只有一页时是否隐藏分页
 * editable: 下拉框是否可输入
-->
<template>
  <div>
    <el-select
      id="select"
      ref="selectTable"
      v-model="selectShowValue"
      :placeholder="props.placeholder"
      :size="props.size"
      :clearable="props.clearable"
      :filterable="editable"
      @input="handleSelectInput"
      @focus="handleSelectFocus"
      @blur="handleSelectBlur"
    >
      <template #empty>
        <el-table
          ref="table"
          :data="props.tableData"
          :highlight-current-row="props.isHighlight"
          :size="props.size"
          :border="props.border"
          @current-change="handleCurrentChange"
          style="width: 100%"
        >
          <!-- <el-table-column type="selection" width="55" /> -->
          <el-table-column
            v-for="field in props.fields"
            :prop="field.prop"
            :label="field.label"
            :width="field.width"
            :show-overflow-tooltip="field.showTooltip"
            :key="field.prop"
          />
        </el-table>
        <div
          class="paging"
          v-if="props.curPage && props.pageSize && props.total"
        >
          <el-pagination
            :current-page="props.curPage"
            :page-size="props.pageSize"
            :pager-count="11"
            :layout="props.pageLayout"
            :total="props.total"
            :background="props.pageBackground"
            :hideOnSinglePage="props.hideOnSinglePage"
            @size-change="sizeChange"
            @current-change="currentChange"
          />
        </div>
      </template>
    </el-select>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from "vue";

interface Field {
  prop: string; //与tableData需要显示的值对应
  label: string;
  width: number;
  showTooltip?: boolean;
}

interface Props {
  data: any;
  //表格属性
  fields: Field[];
  tableData: object[];
  isHighlight?: boolean;
  border?: boolean;
  //下拉框属性
  label?: string;
  value?: string;
  objKey?: string;
  placeholder?: string;
  clearable?: boolean;
  editable?: boolean;
  //分页属性
  curPage?: number;
  pageSize?: number;
  total?: number;
  pageBackground?: boolean;
  pageLayout?: string;
  hideOnSinglePage?: boolean;
  //通用属性
  size?: string;
}
const props = withDefaults(defineProps<Props>(), {
  placeholder: "请选择",
  size: "default",
  isHighlight: true,
  value: undefined,
  label: undefined,
  border: false,
  total: 0,
  pageBackground: false,
  pageLayout: "prev, pager, next",
  hideOnSinglePage: false,
  clearable: false,
  editable: false,
});

interface Emits {
  (e: "update:data", val: any): void;
  (e: "sizeChange", val: number): void;
  (e: "currentChange", val: number): void;
  (e: "inputChange", val: string): void;
}

const emits = defineEmits<Emits>();

const selectTable = ref();
const table = ref();
const selectShowValue = ref(null);
const rowObj = ref(null);

const data = computed({
  get() {
    return props.data;
  },
  set(val) {
    emits("update:data", val);
  },
});

/*onMounted(() => {
  //处理数据回显
  // debugger;
  if (props.data) {
    // 配置label则显示label
    if (typeof props.label !== "undefined") {
      // 配置了value属性，则找到与value属性值一样的表格行对象，将配置的label回显到下拉框
      if (typeof props.value !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.value] === props.data
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.label];
        // 配置了objKey属性，则找到与objKey属性值一样的表格行对象，将配置的label回显到下拉框
      } else if (typeof props.objKey !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.objKey] === props.data[props.objKey]
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.label];
      }
      //没有配置label属性则回显value或者objKey
    } else {
      // 配置了value属性，则找到与value属性值一样的表格行对象，将配置的label回显到下拉框
      if (typeof props.value !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.value] === props.data
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.value];
        // 配置了objKey属性，则找到与objKey属性值一样的表格行对象，将配置的label回显到下拉框
      } else if (typeof props.objKey !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.objKey] === props.data
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.objKey];
      }
    }
  }
});*/

watch(data, (newVal) => {
  if (newVal) {
    // 配置label则显示label
    if (typeof props.label !== "undefined") {
      // 配置了value属性，则找到与value属性值一样的表格行对象，将配置的label回显到下拉框
      if (typeof props.value !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.value] === props.data
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.label];
        // 配置了objKey属性，则找到与objKey属性值一样的表格行对象，将配置的label回显到下拉框
      } else if (typeof props.objKey !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.objKey] === props.data[props.objKey]
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.label];
      }
      //没有配置label属性则回显value或者objKey
    } else {
      // 配置了value属性，则找到与value属性值一样的表格行对象，将配置的label回显到下拉框
      if (typeof props.value !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.value] === props.data
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.value];
        // 配置了objKey属性，则找到与objKey属性值一样的表格行对象，将配置的label回显到下拉框
      } else if (typeof props.objKey !== "undefined") {
        let row = props.tableData.find(
          (item) => item[props.objKey] === props.data
        );
        selectShowValue.value =
          typeof row === "undefined" ? props.data : row[props.objKey];
      }
    }
  }
});

//监听下拉框内容变化，主要用于清空选择框内容
watch(selectShowValue, (newVal) => {
  if (newVal === "") {
    emits("update:data", newVal);
    //取消高亮
    table.value.setCurrentRow(null);
  }
});

/**
 * 点击当前行事件
 * @param val
 */
const handleCurrentChange = (val: any) => {
  if (!val) {
    return;
  }
  rowObj.value = { ...val };
  // 如果没有配置label则显示value或者objKey
  setLabel(val);
  //  设置双向绑定值
  if (typeof props.value !== "undefined") {
    emits("update:data", val[props.value]);
  } else {
    emits("update:data", val);
  }
  selectTable.value.blur();
};

/**
 * 下拉框输入值变化
 */
const handleSelectInput = () => {
  emits("inputChange", selectTable.value.$el.querySelector('input').value);
};

/**
 * 每页大小改变
 * @param val
 */
const sizeChange = (val: number) => {
  emits("sizeChange", val);
};

/**
 * 当前页改变
 * @param val
 */
const currentChange = (val: number) => {
  emits("currentChange", val);
};

/**
 * 设置下拉框选择显示文本内容
 * @param val
 */
const setLabel = (val: any) => {
  // 如果没有配置label则显示value或者objKey
  if (typeof props.label === "undefined") {
    // 如果配置了value,则显示value
    if (typeof props.value !== "undefined") {
      selectShowValue.value = val[props.value];
    } else if (typeof props.objKey !== "undefined") {
      //没有配置value但配置了objKey,则显示objKey
      selectShowValue.value = val[props.objKey];
    }
  } else {
    selectShowValue.value = val[props.label];
  }
};

/**
 * 获得焦点的时候提示父组件
 */
const handleSelectFocus = () =>{
  emits("inputFocus",selectTable.value.$el.querySelector('input').value);
};

const handleSelectBlur = () =>{
  emits("inputBlur",selectTable.value.$el.querySelector('input').value);
};

/**
 * 提供一个清除内部数据的方法，用于清空选择框内容
 */
const clearSelectData = () => {
  emits("update:data", "");
  selectShowValue.value = null;
}
defineExpose({
  clearSelectData
})
</script>

<style scoped>
.paging {
  width: 100%;
  display: flex;
  justify-content: center;
}
</style>
